#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File    : /decorator_class.py
@Time    : 2021-03-16 22:34:34
@Author  : Gray Snail
@Version : 1.0
@Contact : shtao2011@sina.com
@License : Copyright (c) 2021 Gray Snail
@Desc    : None
'''


class cls_for_func(object):
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print('before')
        res = self.func(*args, **kwargs)
        print('after')
        return res


@cls_for_func
def test():
    print('run...')


# test = cls_for_func(test)
# 如果要传参，则init中接受参数，call中接受函数？
class cls_for_func1(object):
    def __init__(self, p1, p2):
        self.p1 = p1
        self.p2 = p2

    def __call__(self, func):
        print(self.p1)

        def inner(*args, **kwargs):
            print(func.__name__)
            return func(*args, **kwargs)

        print(self.p2)

        return inner


@cls_for_func1('hh', 'heh')
def test2():
    print('test2')


# test2 = cls_for_func1('hh', 'heh')(test2)()


class cls_for_cls:
    def __init__(self, cls):
        self.wrapper = cls

    def __call__(self, *args, **kwargs):
        # 装饰类，则__call__中需要返回类对象
        return self.wrapper(*args, **kwargs)


@cls_for_cls
class Foo(object):
    def __init__(self, name):
        self.name = name

    def show(self):
        print(self.name)


# Foo = cls_for_cls(Foo)
class cls_for_cls1:
    def __init__(self, *args, **kwargs):
        print(*args)
        print(**kwargs)

    def __call__(self, cls):
        return cls


# Foo = cls_for_cls('aaa')(Foo)

'''
函数和类构造出的装饰器本质是一样的

类装饰器不过是利用构造函数减少了函数装饰器最外层的函数嵌套
类装饰器必须重写__call__方法，其本身也是也是可执行对象（Functional）
'''


def test_cls_4_cls():
    foo = Foo('John')
    foo.show()


if __name__ == "__main__":
    test()

    test_cls_4_cls()